<template>
  <div>
    <div class="virtual-scroll-container">
      <div
        class="scroll-area"
        ref="scrollContainer"
        @scroll="handleScroll"
      >
        <!-- 占位元素，用于撑开滚动条 -->
        <div
          class="spacer-before"
          :style="{ height: spacerBeforeHeight + 'px' }"
        ></div>

        <!-- 可见区域的实际元素 -->
        <div class="visible-items">
          <div
            v-for="item in visibleItems"
            :key="item.id"
            class="item"
            :style="{ height: itemHeight + 'px' }"
          >
            <div class="item-content">
              <h3>项目 {{ item.id }}</h3>
              <p>这是第 {{ item.id }} 个项目的内容</p>
              <p>滚动位置: {{ Math.round(scrollTop) }}px</p>
            </div>
          </div>
        </div>

        <!-- 占位元素，用于撑开滚动条 -->
        <div
          class="spacer-after"
          :style="{ height: spacerAfterHeight + 'px' }"
        ></div>
      </div>
    </div>

    <!-- 调试信息 -->
    <div class="debug-info">
      <p>总数据量: {{ data?.length }}</p>
      <p>可见项目: {{ startIndex }} - {{ endIndex }}</p>
      <p>滚动位置: {{ Math.round(scrollTop) }}px</p>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, useTemplateRef } from 'vue'

// // 模拟大量数据
// const totalItems = 40
// const itemHeight = 80 // 每个项目的固定高度
// const containerHeight = 500 // 容器高度
// const bufferSize = 5 // 缓冲区大小，多渲染几个项目以提升体验
const props = defineProps({
  data: {
    type: Array,
    default: () => []
  },
  itemHeight: {
    type: Number,
    default:80
  },
  containerHeight: {
    type: Number,
    default:500
  },
  bufferSize: {
    type: Number,
    default:5
  }
})


// 响应式数据
const scrollTop = ref(0)
const scrollContainer = useTemplateRef('scrollContainer')

// // 生成模拟数据
// const allItems = Array.from({ length: props.data.length }, (_, index) => ({
//   id: index + 1,
//   name: `项目 ${index + 1}`,
//   content: `这是第 ${index + 1} 个项目的详细内容`
// }))

// 计算可见区域的索引范围
const startIndex = computed(() => {
  const index = Math.floor(scrollTop.value / props.itemHeight)
  return Math.max(0, index - props.bufferSize)
})

const endIndex = computed(() => {
  const index = Math.ceil((scrollTop.value + props.containerHeight) / props.itemHeight)
  return Math.min(props.data.length - 1, index + props.bufferSize)
})

// 可见区域的项目
const visibleItems = computed(() => {

  return props.data.slice(startIndex.value, endIndex.value + 1) as { id: number; name: string; content: string }[]
})

// 上方占位元素的高度
const spacerBeforeHeight = computed(() => {
  return startIndex.value * props.itemHeight
})

// 下方占位元素的高度
const spacerAfterHeight = computed(() => {
  return (props.data.length - endIndex.value - 1) * props.itemHeight
})

// 滚动事件处理
const handleScroll = (event: Event) => {
  const target = event.target as HTMLElement
  scrollTop.value = target.scrollTop
}

// 滚动到指定位置的方法
const scrollToIndex = (index: number) => {
  if (scrollContainer.value) {
    const targetScrollTop = index * props.itemHeight
    scrollContainer.value.scrollTo({
      top: targetScrollTop,
      behavior: 'smooth'
    })
  }
}

// 滚动到顶部
const scrollToTop = () => {
  scrollToIndex(0)
}

// 滚动到底部
const scrollToBottom = () => {
  scrollToIndex(props.data.length - 1)
}

onMounted(() => {
  console.log('虚拟滚动初始化完成')
  console.log(`总项目数: ${props.data.length}`)
  console.log(`项目高度: ${props.itemHeight}px`)
  console.log(`容器高度: ${props.containerHeight}px`)
})

// 暴露方法给外部使用
defineExpose({
  scrollToIndex,
  scrollToTop,
  scrollToBottom
})
</script>

<style scoped lang="scss">
.virtual-scroll-container {
  width: 100%;
  height: 500px;
  border: 2px solid #e0e0e0;
  border-radius: 8px;
  overflow: hidden;
  // padding:10px;
}

.scroll-area {
  width: 100%;
  height: 100%;
  overflow-y: auto;
  overflow-x: hidden;
}

.spacer-before,
.spacer-after {
  width: 100%;
}

.visible-items {
  width: 100%;
}

.item {
  width: 100%;
  box-sizing: border-box;
  border-bottom: 1px solid #f0f0f0;
  display: flex;
  align-items: center;
  transition: background-color 0.2s;

  &:hover {
    background-color: #f8f9fa;
  }
}

.item-content {
  padding: 15px 20px;
  width: 100%;

  h3 {
    margin: 0 0 8px 0;
    font-size: 16px;
    font-weight: 600;
    color: #333;
  }

  p {
    margin: 0 0 4px 0;
    font-size: 14px;
    color: #666;

    &:last-child {
      margin-bottom: 0;
      font-size: 12px;
      color: #999;
    }
  }
}

.debug-info {
  margin-top: 20px;
  padding: 15px;
  background-color: #f8f9fa;
  border-radius: 6px;
  border: 1px solid #e9ecef;

  p {
    margin: 0 0 8px 0;
    font-family: 'Courier New', monospace;
    font-size: 13px;
    color: #495057;

    &:last-child {
      margin-bottom: 0;
    }
  }
}

/* 滚动条样式优化 */
.scroll-area::-webkit-scrollbar {
  width: 8px;
}

.scroll-area::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 4px;
}

.scroll-area::-webkit-scrollbar-thumb {
  background: #c1c1c1;
  border-radius: 4px;

  &:hover {
    background: #a8a8a8;
  }
}
</style>
